using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using Krile.Kernel.Control.Surface;

namespace Krile.Forms.MainForm.Controls.XTab
{
    public class XTabMouseManager : IDisposable
    {
        XTab parent;
        protected XTab Parent { get { return parent; } }
        XTabItemBase lastPointed;
        ToolTip toolTip;
        public XTabMouseManager(XTab par)
        {
            //init valiables
            parent = par;
            lastPointed = null;
            toolTip = new ToolTip();
            toolTip.ShowAlways = true;
            toolTip.Active = false;
            //mouse event set
            parent.AllowDrop = true;
            parent.MouseLeave += new EventHandler(OnMouseLeave);
            parent.MouseMove += new MouseEventHandler(OnMouseMove);
            parent.MouseClick += new MouseEventHandler(OnMouseClick);
            parent.MouseDoubleClick += new MouseEventHandler(OnMouseDoubleClick);
            parent.MouseUp += new MouseEventHandler(OnMouseUp);
            parent.MouseDown += new MouseEventHandler(OnMouseDown);
            parent.DragOver += new DragEventHandler(OnDragOver);
            parent.DragDrop += new DragEventHandler(OnDragDrop);
            parent.DragLeave += new EventHandler(OnDragLeave);
        }

        protected virtual void OnMouseDown(object sender, MouseEventArgs e)
        {
            XTabItemBase tib = GetItemByPoint(e.Location);
            if (tib != null)
                tib.OnMouseDown(sender, e);
        }

        protected virtual void OnMouseUp(object sender, MouseEventArgs e)
        {
            XTabItemBase tib = GetItemByPoint(e.Location);
            if (tib != null)
                tib.OnMouseUp(sender, e);
        }

        protected virtual void OnMouseClick(object sender, MouseEventArgs e)
        {
            XTabItemBase tib = GetItemByPoint(e.Location);
            if (tib != null)
                tib.OnMouseClick(sender, e);
        }

        protected virtual void OnMouseDoubleClick(object sender, MouseEventArgs e)
        {
            XTabItemBase tib = GetItemByPoint(e.Location);
            if (tib != null)
                tib.OnMouseDoubleClick(sender, e);
        }

        protected XTabItemBase prevPoint = null;
        protected virtual void OnMouseMove(object sender, MouseEventArgs e)
        {
            XTabItemBase tib = GetItemByPoint(e.Location);
            if (tib != null && tib is XTabItem)
                prevPoint = tib;
            if (tib != null)
            {
                //found
                if (!tib.Equals(lastPointed))
                {
                    releaseLastPointed();
                    lastPointed = tib;
                    toolTip.SetToolTip(parent, tib.Name);
                    toolTip.Active = true;
                    lastPointed.OnMouseEnter(sender, e);
                }
                tib.OnMouseMove(sender, e);
            }
            else
            {
                //not found
                releaseLastPointed();
            }
        }

        protected XTabItemBase GetItemByPoint(Point location)
        {
            foreach (XTabItemBase tib in parent.GetItemBaseArray())
                if (isPointInnerRect(location, tib.ClientRectangle))
                    return tib;
            return null;
        }

        protected virtual void OnMouseLeave(object sender, EventArgs e)
        {
            releaseLastPointed();
        }

        protected bool isPointInnerRect(Point pt, Rectangle rect)
        {
            if (pt.X < rect.Left || pt.X > rect.Right ||
                pt.Y < rect.Top || pt.Y > rect.Bottom)
                return false;
            else
                return true;
        }

        protected void releaseLastPointed()
        {
            if (lastPointed != null)
            {
                lastPointed.OnMouseLeave(parent, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0));
                lastPointed = null;
                toolTip.Active = false;
            }
        }

        protected virtual void OnDragOver(object sender, DragEventArgs e)
        {
            var xtd = e.Data.GetData(typeof(XTabDroppable)) as XTabDroppable;
            if (xtd != null && xtd.DroppableThis(this.parent))
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.None;
            Point cp = parent.PointToClient(new Point(e.X, e.Y));
            OnMouseMove(sender, new MouseEventArgs(MouseButtons.None, 0, cp.X, cp.Y, 0));
        }

        protected virtual void OnDragDrop(object sender, DragEventArgs e)
        {
            var xtd = e.Data.GetData(typeof(XTabDroppable)) as XTabDroppable;
            if (xtd != null && xtd.DroppableThis(this.parent))
            {
                var dest = GetItemByPoint(parent.PointToClient(new Point(e.X, e.Y))) as XTabItem;
                if (dest == null && xtd.DroppableNew)
                    xtd.OnDropToNew(parent);
                else if (dest != null && xtd.DroppableAppend)
                {
                    xtd.OnDropToAppend(parent, dest);
                    parent.SelectedItem = dest;
                }
            }
        }

        protected virtual void OnDragLeave(object sender, EventArgs e)
        {
            releaseLastPointed();
        }

        public void Dispose()
        {
            toolTip.Dispose();
        }
    }
}
